/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package jclient;

/**
 *
 * @author famiglia
 */
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class Client extends JFrame//Finestra principale
{

    private JLabel labelmyid = null;
    private JLabel labelidselect = null;
    private JLabel insNome = null;
    private JLabel insHost = null;
    private JButton connetti = null;
    private JButton parla = null;
    private JTextField nome = null;
    private JTextField host = null;
    JComboBox editableComboBox;
    private Socket socket = null;
    private int id;
    private String nomeUtente;
    private ArrayList<Utente> utentiList = null;
    private boolean isConnesso = false;
    public ArrayList<FinestraChat> winAperte = null;
    static Client app ;
   

    private class Leggi extends Thread{//Legge dal Server
        public void run(){
        BufferedReader in = null;
        String linea;
        String[] temp= null;
        try{
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while((linea = in.readLine()) !=null)//legge un messaggio del tipo TipoMex|IdMittente|Messaggio
            {
                temp = linea.split("\\|");//Divide il messaggio nelle sue varie parti
                int tipoMex = Integer.parseInt(temp[0]);
                int idMittente = Integer.parseInt(temp[1]);
                boolean msgInviato = false;
                String nomeMittente = "";
                for(int i=0;i<utentiList.size();i++)
                {
                    if(idMittente == utentiList.get(i).getId())
                        nomeMittente = utentiList.get(i).getNome();
                }
                String Msg = nomeMittente + " : " + temp[2];
                if(tipoMex==-1)//Caso messaggio di testo ricevuto
                {
                    if(winAperte.isEmpty())//Se non vi sono finestre aperte ne apre una
                    {
                        FinestraChat finestra = new FinestraChat(app,idMittente,nomeMittente);
                        winAperte.add(finestra);
                        winAperte.get(winAperte.size()-1).stampaMsg(Msg);
                    }
                    else//Se vi sono finestre aperte
                    {
                        //Controlla se la finestra desiderata è già aperta
                        for(int i=0;i<winAperte.size();i++)
                        {
                            if(winAperte.get(i).getmyId() == idMittente)//Se aperta stampa il msg in quella
                            {
                                winAperte.get(i).stampaMsg(Msg);
                                msgInviato = true;
                            }

                        }
                        if(!msgInviato)//Se il msg non è ancora stato inviato apre una finestra e lo stampa là
                        {
                            FinestraChat finestra = new FinestraChat(app,idMittente,nomeMittente);
                            winAperte.add(finestra);
                            winAperte.get(winAperte.size()-1).stampaMsg(Msg);
                            msgInviato = true;
                        }
                    }
                }
                else if(tipoMex==-2)//Caso utente disconnesso
                {
                    int idCanc = -1;
                    int idTemp = Integer.parseInt(temp[1]);
                    if(id > idTemp)//Aggiorna il proprio id
                        id = id -1;
                    for(int i=0;i<utentiList.size();i++)//Cancella l'utente disconnesso
                    {
                        if(utentiList.get(i).getId()==idTemp)
                        {
                            utentiList.remove(i);
                            idCanc = i;
                        }
                    }
                    for(int j=idCanc; j<utentiList.size();j++)//Aggiorna gli id nella utentiList
                    {
                        int newid = utentiList.get(j).getId() -1;
                        utentiList.get(j).setId(newid);
                    }
                    editableComboBox.removeAllItems();//Rimuove tutti gli oggetti dalla ComboBox
                    for(int i=0;i<utentiList.size();i++)//Inserisce gli utenti aggiornati
                    {
                         if(id!=utentiList.get(i).getId())
                            editableComboBox.addItem(utentiList.get(i).getNome());
                    }
                    if(!winAperte.isEmpty())//Se ci sono finestre aperte
                    {
                        for(int i=0;i<winAperte.size();i++)
                        {
                            if(winAperte.get(i).getmyId()==idCanc)//Se c'è una finestra aperta
                            {                                     //corrispondente all'utente disconnesso la chiude
                                winAperte.get(i).winChiusura();
                                winAperte.remove(i);
                            }
                        }
                    }
                }
                else if(tipoMex==-3)//Caso utente connesso
                {
                        int idTemp = Integer.parseInt(temp[1]);
                        utentiList.add(new Utente(idTemp,temp[2]));//L'utente viene aggiunto alla lista utenti
                        if(id!=idTemp)
                            editableComboBox.addItem(temp[2]);//L'utente viene aggiunto alla combobox
                }
            }
            }catch(IOException ex){}
        }
    }


    public Client()
    {
        setTitle("Progetto Java-Programmazione II");
        labelmyid = new JLabel("Mio Nome : nessuno");
        labelidselect = new JLabel("Utente selezionato : nessuno");
        insNome = new JLabel("Inserisci NickName desiderato");
        insHost = new JLabel("Inserisci Host desiderato");
        connetti = new JButton("Connetti");
        parla = new JButton("Parla con");
        nome = new JTextField(10);
        host = new JTextField(10);
        host.setText("localhost");
        connetti.addActionListener(new ActionListener()//Azione compiuta al click sul bottone connetti
        {
            public void actionPerformed(ActionEvent e)
            { 
                String linea=null;
                String[]temp = null;
                String[] ids = null;
                String[] id0nome1 = null;
                if(nome.getText().trim().equals("")|| host.getText().trim().equals(""))//Controlla che il nome sia stato scritto
                {
                    JOptionPane.showMessageDialog(rootPane, "Inserire un nome o un host!");

                }
                else
                {
                    if(isConnesso)
                    {
                        JOptionPane.showMessageDialog(rootPane, "Sei già connesso!");
                    }
                    else
                    {
                        try
                        {
                            // Apre una connessione socket
                            socket = new Socket(host.getText(), 2223);
                            isConnesso = true;
                        }catch(Exception s) { JOptionPane.showMessageDialog(rootPane, s.getMessage());isConnesso = false;}
                        if(isConnesso)
                        {
                            try{
                                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                                DataOutputStream out = new DataOutputStream(socket.getOutputStream());
                                out.writeBytes(""+nome.getText() +"\n");//Invia al Server il nome desiderato
                                linea = in.readLine();//Legge dal Server l'id assegnato
                                id = Integer.parseInt(linea);//Imposta l'id
                                linea = "";
                                nomeUtente = in.readLine();//Legge dal Server il nome assegnato e lo imposta
                                labelmyid.setText("Mio Nome: "+nomeUtente);
                                linea = in.readLine();//Legge dal Server la lista degli utenti già collegati
                                temp = linea.split("\\|");//Divide le parti del msg
                                int tipoMex = Integer.parseInt(temp[0]);
                                if(tipoMex==-3)
                                {
                                    utentiList = new ArrayList<Utente>();//Inizializza una lista utenti
                                    ids = temp[2].split(",");//Divide la lista utenti in singoli utenti
                                    if (ids.length == 1)//Caso in cui vi sia un solo utente in lista
                                    {
                                        id0nome1 = ids[0].split(":");//Divide il singolo utente in: Id nel campo 0 e Nome nel campo 1
                                        utentiList.add(new Utente(Integer.parseInt(id0nome1[0]),id0nome1[1]));//Aggiunge materialmente il nuovo utente
                                        if(!(id==Integer.parseInt(id0nome1[0])))
                                            editableComboBox.addItem(id0nome1[1]);//Aggiunge elementi alla ComboBox
                                    }
                                    else//Caso in cui vi siano più utenti in lista
                                    {
                                        for(int i=0;i<ids.length;i++)
                                        {
                                            id0nome1 = ids[i].split(":");
                                            utentiList.add(new Utente(Integer.parseInt(id0nome1[0]),id0nome1[1]));
                                            if(!(id==Integer.parseInt(id0nome1[0])))
                                                editableComboBox.addItem(id0nome1[1]);
                                        }
                                    }
                                }
                                out.writeBytes("-3|"+id+"|-1|"+ nomeUtente +"\n");//Scrive al Server che l'utente si è connesso
                                nome.setEnabled(false);//Il campo nome viene chiuso a modifiche
                                host.setEditable(false);//Il campo host viene chiuso a modifiche
                                new Leggi().start();//Parte il thread relativo alla lettura continua da Server
                                winAperte = new ArrayList<FinestraChat>();//Viene inizalizzata la lista delle finestre chat aperte
                            }catch(IOException ex){}
                        }
                    }
                }
            }
            });


            parla.addActionListener(new ActionListener()//Azione compiuta al click sul bottone parla
             {
                   public void actionPerformed(ActionEvent e)
                    {
                        int id=-1;
                        String nome = "";
                        boolean aperta= false;
                        if(isConnesso && !((String)editableComboBox.getSelectedItem()==null))//Controlla che sei connesso e che hai selezionato un nome dalla combobox
                        {
                            for(int i=0;i<utentiList.size();i++)
                            {
                                if(utentiList.get(i).getNome().equalsIgnoreCase((String)editableComboBox.getSelectedItem()))
                                {
                                    id = utentiList.get(i).getId();
                                    nome = utentiList.get(i).getNome();
                                    break;
                                }
                            }
                            //Inizio controllo delle finestre di chat
                            if(winAperte.isEmpty())//Caso in cui non vi sono finestre aperte
                            {
                                //Apre direttamente una nuova finestra
                                FinestraChat finestra = new FinestraChat(app,id,nome);
                                winAperte.add(finestra);//Aggiunge la finestra aperta alla lista finestre
                                aperta = true;
                            }
                            else//Caso in cui vi sono finestre già aperte
                            {
                                for(int i=0;i<winAperte.size();i++)
                                {
                                    if(winAperte.get(i).getmyId() == id)//Si desidera parlare con un utente la cui finestra è già aperta
                                    {
                                        JOptionPane.showMessageDialog(rootPane, "La finestra è gia aperta!");
                                        aperta = true;
                                    }

                                }
                            }
                            if(!aperta)//Se non abbiamo ancora aperto la finestra ne apriamo una
                            {
                                FinestraChat finestra = new FinestraChat(app,id,nome);
                                winAperte.add(finestra);
                                aperta = true;
                            }
                        }
                    }

              });

        ActionListener selectionListener = new SelectionListener();
        // Inizializza un JComboBox editabile
        editableComboBox= new JComboBox();
        editableComboBox.addActionListener(selectionListener);//Viene assegnato un nuovo ActionListener alla combobox
        Container panPrincipale = getContentPane();//Viene creato il pannello principale
        panPrincipale.setLayout(new BorderLayout());//Imposta il layout per il pannello principale
        Container panCentro = new Panel();//Pannelli secondari che contengono i vari componenti
        Container panNord = new Panel();
        Container panSud = new Panel();
        panSud.setLayout(new GridLayout(2,2));
        Container panEst = new Panel();
        panNord.add(connetti);
        panNord.add(labelmyid);
        panEst.add(editableComboBox);
        panCentro.add(labelidselect);
        panSud.add(insNome);
        panSud.add(nome);
        panSud.add(insHost);
        panSud.add(host);
        panPrincipale.add(panNord, BorderLayout.NORTH);//Impostazione dei pannelli secondari nel pannello principale
        panPrincipale.add(panEst,BorderLayout.EAST);
        panPrincipale.add(parla,BorderLayout.WEST);
        panPrincipale.add(panCentro,BorderLayout.CENTER);
        panPrincipale.add(panSud,BorderLayout.SOUTH);
        addWindowListener(new WindowAdapter()
        {
            public void windowClosing(WindowEvent e)//Evento chiusura finestra principale(Chiusura programma)
            { 
                String linea = null;
                if(isConnesso)
                {

                    linea = "-2|"+id+"|-1|CANC";
                    try{
                        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
                        out.writeBytes(linea);//Invia al Server il msg che il client si è disconnesso
                        out.close();
                    }catch(IOException ex){}
                    for(int i=0;i<winAperte.size();i++)//Chiude tutte le finestre
                        winAperte.get(i).winChiusura();
                }

                System.exit(0);
            }
        });
        pack();//Fà impiegare il minor spazio possibile ai componenti in finestra
        setVisible(true);//Rende visibile la finestra principale
        setResizable(false);
    }

    class SelectionListener implements ActionListener {//Evento ComboBox
      public void actionPerformed(ActionEvent e) {
        JComboBox cb = (JComboBox)e.getSource();
        String selectedItem = (String)cb.getSelectedItem();
        if(selectedItem==null)
            labelidselect.setText("Utente selezionato : nessuno");
        else
            labelidselect.setText("Utente selezionato: "+selectedItem);
      }
    }

    public boolean Connesso()
    {
        return this.isConnesso;
    }

    public int getClientId()
    {
        return this.id;
    }

    public String getNomeClient()
    {
        return this.nomeUtente;
    }

    public Socket getClientSocket()
    {
        return this.socket;
    }

    public static void main(String[] args)
    {
        app = new Client();

    }
}
